#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>

const static std::string sep ="\r\n";

// 添加报头
std::string EnCode(const std::string& jsonstr)
{
    int len = jsonstr.size();
    std::string lenstr  = std::to_string(len);
    return lenstr + sep + jsonstr + sep;
}

// 获取一个完成的报文
std::string DeCode(std::string& packagestream)
{
    auto pos = packagestream.find(sep);
    if(pos == std::string::npos)// 只有长度，没有报文
        return "";
    // 获取报文中的json串长度
    std::string lenstr = packagestream.substr(0, pos);
    int len = std::stoi(lenstr);
    // 求出一个完整报文的长度
    int total = lenstr.size() + len + 2*sep.size();
    if(packagestream.size() < total) // 当前的数据流中，不够一个报文
        return "";
    // 获取一个完整的报文
    std::string jsonstr = packagestream.substr(pos+sep.size(), len);
    // 删除拿走的报文
    packagestream.erase(0,total);
    return jsonstr;
}


class Request
{
public:
    Request(){}
    Request(int x, int y, char oper)
        : _x(x), _y(y), _oper(oper)
    {
    }

    ~Request()
    {
    }
    // 序列化
    bool Serialize(std::string *out)
    {
        Json::Value root; // 创建一个 万能对象
        root["x"] = _x; // 使用键值对的方式赋值
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;// 创建一个序列化对象
        std::string s = writer.write(root);// 序列化
        *out = s;// 将序列化结果带出去
        return true;
    }
    
    // 反序列化
    bool Deserialize(const std::string &in)
    {
        Json::Value root;// 创建一个 万能对象
        Json::Reader reader;// 创建一个反序列化对象
        bool res = reader.parse(in, root);// 反序列化
        if (!res)
            return false;
        _x = root["x"].asInt();// 将反序列化的结果, 给成员属性
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }

    void SetValue(int x, int y, char oper)
    {
        _x = x;
        _y = y;
        _oper = oper;
    }

    void SetX(int x)
    {
        _x = x;
    }

    void SetY(int y)
    {
        _y = y;
    }

    void SetOper(char oper)
    {
        _oper = oper;
    }

    int GetX()
    {
        return _x;
    }

    int GetY()
    {
        return _y;
    }

    char GetOper()
    {
        return _oper;
    }

    void Print()
    {
        std::cout << "_x: " << _x << " _y: " << _y << " _oper: " << _oper << std::endl;
    }

private:
    int _x;
    int _y;
    char _oper;
};



class Response
{
public:
    Response()
        : _result(0), _code(0), _desc("success")
    {
    }

    ~Response()
    {
    }

     // 序列化
    bool Serialize(std::string *out)
    {
        Json::Value root;// 创建一个 万能对象
        root["result"] = _result;// 使用键值对的方式赋值
        root["code"] = _code;
        root["desc"] = _desc;
        Json::FastWriter writer;// 创建一个序列化对象
        std::string s = writer.write(root);// 序列化
        *out = s;// 将序列化结果带出去
        return true;
    }

    // 反序列化
    bool Deserialize(const std::string &in)
    {
        Json::Value root;// 创建一个 万能对象
        Json::Reader reader;// 创建一个反序列化对象
        bool res = reader.parse(in, root);// 反序列化
        if (!res)
            return false;
        _result = root["result"].asInt();// 将反序列化的结果, 给成员属性
        _code = root["code"].asInt();
        _desc = root["desc"].asString();
        return true;
    }

    void SetResult(int result)
    {
        _result = result;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    void SetDesc(const std::string &desc)
    {
        _desc = desc;
    }

    int GetResult()
    {
        return _result;
    }

    int GetCode()
    {
        return _code;
    }

    std::string GetDesc()
    {
        return _desc;
    }

    void Print()
    {
        std::cout << "_result: " << _result << " : _code: " << _code << " : _desc: " << _desc << std::endl;
    }

private:
    int _result;       // 计算结果
    int _code;         // 退出码
    std::string _desc; // 退出码描述
};


// 构建一个简单的工厂
class Factory
{
public:
    static std::shared_ptr<Request> BuildRequest()
    {
        return std::make_shared<Request>();
    }

    static std::shared_ptr<Response> BuildResponse()
    {
        return std::make_shared<Response>();
    }
};